package Practica1;
import java.util.*;
import java.awt.Color;
import java.io.File;

import java.io.IOException;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import javax.swing.JOptionPane;

public class Solucion {
	
	int esfuerzo, satisfaccion, solucion[], numveces = 1000000, encontrado=0;
	Archivo2 archivo;
		
	public Solucion(Archivo2 archivo2){
		
		archivo = archivo2;
		ArrayList<int[]> solucion1 = new ArrayList<int[]>();
		
		solucion1 = sacarSolucion();
		mostrarSoluciones(solucion1);
		calculoSpread(solucion1);
		calculoSpacing(solucion1);
		dibujoGrafico(solucion1);
	}

	private ArrayList<int[]> sacarSolucion() {
		
		ArrayList<int[]> listaSoluciones = new ArrayList<int[]>();
		
		for(int w=0;w<numveces;w++){			
			solucion = new int[archivo.getNrecursos()+2];
			satisfaccion = 0;
			esfuerzo=0;
		
			for(int i=0;i<archivo.getNrecursos();i++){
				solucion[i] = (int)(Math.random()*(1-0+1)+0);
			}
		
			for(int i=0; i<archivo.getNrecursos();i++){
				int num=0;
				if(solucion[i]==1){
					for(int j=1;j<=archivo.getNclientes();j++){
						satisfaccion = satisfaccion + (archivo.satisfaccion[i][j] * archivo.pesocli[j]);
						num = num + archivo.satisfaccion[i][j]*archivo.pesocli[j];
					}
					esfuerzo = esfuerzo + archivo.esfuerzo[i];
				}
			}
		
			solucion[archivo.getNrecursos()] = satisfaccion;
			solucion[archivo.getNrecursos()+1] = esfuerzo;
			
			//mostrarSolucion(solucion,archivo);
			
			int[] sol;
			if(solucion[21]<60){
				if(cumpleDependencias(solucion)){
					
					for(int i=0;i<listaSoluciones.size();i++){
						sol = listaSoluciones.get(i);
						if(esfuerzo==sol[archivo.getNrecursos()+1])
						{
							//JOptionPane.showMessageDialog(null, "Esf1: "+esfuerzo+" esf2: "+sol[archivo.getNrecursos()+1]);
							if(satisfaccion>sol[archivo.getNrecursos()]){
								//JOptionPane.showMessageDialog(null, "Sat1: "+satisfaccion+" sat2: "+sol[archivo.getNrecursos()]);
								listaSoluciones.remove(sol);
								listaSoluciones.add(solucion);								
							}
							encontrado=1;
						}								
					}						
					
					if(encontrado==0){
						listaSoluciones.add(solucion);
					}												
				}
			}
			encontrado=0;
		}
		
		//mostrarSoluciones(listaSoluciones);		
		if(listaSoluciones.size()>2){
			listaSoluciones = ordenar(listaSoluciones);
		}
		
		return listaSoluciones;	
		
	}

	private ArrayList<int[]> ordenar(ArrayList<int[]> listaSoluciones) {
		
		ArrayList<int[]> aux= new ArrayList<int[]>();
		int menor, posicion;
		int[] sol;
		
		do{
			menor=100;
			posicion=0;
			
			for(int i=0;i<listaSoluciones.size();i++){
				sol = listaSoluciones.get(i);
				if(sol[archivo.getNrecursos()+1]<menor){
					posicion = i;
					menor=sol[archivo.getNrecursos()+1];
				}
			}
			
			sol = listaSoluciones.get(posicion);
			aux.add(sol);
			listaSoluciones.remove(posicion);
		
		}while(listaSoluciones.size()>0);
		
		return aux;
	}

	private void mostrarSolucion(int[] sol) {
		
		System.out.println("\nSolucion: ");
		for(int i=0;i<=archivo.getNrecursos()+1;i++){
			System.out.print(" "+sol[i]+" ");
		}
		System.out.println("\n");
	}
	
	private void mostrarSoluciones(ArrayList<int[]> listaSoluciones) {
		int[] num;
		for(int i=0;i<listaSoluciones.size();i++){
			num = listaSoluciones.get(i);
			System.out.println("\nSolucion "+(i)+": ");
			for(int j=0;j<num.length;j++){
				System.out.print(" "+num[j]);
			}
		}		
	}
	
	private boolean cumpleDependencias(int[] sol) {
		
		int dep1,dep2;
		
		for(int i=0;i<archivo.dependencias.length;i++){
			dep1 = archivo.dependencias[i][0];
			dep2 = archivo.dependencias[i][1];
			if(sol[dep1-1]==1){
				if(sol[dep2-1]==0){
					return false;
				}
			}
		}		
		return true;
	}
	
	private void calculoSpread(ArrayList<int[]> solucion) {
		
		int[] vect1, vect2;
		double media=0, sumatoria=0, euclidea, spread, minspread=12, maxspread=16;
		int primero,ultimo;
		
		vect1 = solucion.get(0);
		vect2 = solucion.get(solucion.size()-1);
		primero = vect1[archivo.getNrecursos()+1];
		ultimo = vect2[archivo.getNrecursos()+1];
		
		for(int i=0;i<solucion.size()-1;i++){
			vect1 = solucion.get(i);
			vect2 = solucion.get(i+1);
			media = media + (vect2[archivo.getNrecursos()+1]-vect1[archivo.getNrecursos()+1]);			
		}
		media = media / solucion.size();
		
		for(int i=0;i<solucion.size()-1;i++){
			euclidea = 0;
			vect1 = solucion.get(i);
			vect2 = solucion.get(i+1);
			
			euclidea = Math.sqrt(Math.pow(vect2[archivo.getNrecursos()]-vect1[archivo.getNrecursos()], 2) + Math.pow(vect2[archivo.getNrecursos()+1]-vect1[archivo.getNrecursos()+1], 2)); 
			sumatoria = sumatoria + (euclidea - media);			
		}		
		spread = (primero+ultimo+sumatoria)/(primero+ultimo+((solucion.size()-1)*media));
		
		spread = (spread-minspread)/(maxspread-minspread);
		
		System.out.println("\nSpread: "+spread);		
	}
	
	private void calculoSpacing(ArrayList<int[]> solucion) {
		
		int N;
		double euclidea, media=0, spacing=0, valor, minspacing=3, maxspacing=5;
		int[] vect1, vect2;
		
		vect1 = solucion.get(solucion.size()-1);
		N = vect1[archivo.getNrecursos()+1]-1;
		
		for(int i=0;i<solucion.size()-1;i++){
			vect1 = solucion.get(i);
			vect2 = solucion.get(i+1);
			media = media + (vect2[archivo.getNrecursos()+1]-vect1[archivo.getNrecursos()+1]);			
		}
		media = media / solucion.size();
		
		for(int j=0;j<solucion.size();j++){
			vect1 = solucion.get(j);
			valor = 0;
			for(int i=0;i<N;i++){				
				vect2 = solucion.get(i);				
				euclidea = Math.abs(Math.sqrt(Math.pow(vect2[archivo.getNrecursos()]-vect1[archivo.getNrecursos()], 2) + Math.pow(vect2[archivo.getNrecursos()+1]-vect1[archivo.getNrecursos()+1], 2)));				
				valor = Math.pow(1 -(euclidea/media), 2);				
			}
			spacing = spacing + Math.pow(valor, 0.5);
		}
		spacing = spacing/(solucion.size()*N);
		spacing = (spacing-minspacing)/(maxspacing-minspacing);
		System.out.println("Spacing: "+spacing);
	}
	
	private void dibujoGrafico(ArrayList<int[]> solucion) {
		
		int[] vect1;
		XYSeries series = new XYSeries("Soluciones");
		
		for(int i=1;i<solucion.size();i++){
			vect1 = solucion.get(i);
			series.add(vect1[archivo.getNrecursos()+1],vect1[archivo.getNrecursos()]);
		}
		
		XYSeriesCollection dataset = new XYSeriesCollection();
		dataset.addSeries(series);
		JFreeChart chart = ChartFactory.createScatterPlot("Frente de Pareto - 1.000.000 ejecuciones", "Esfuerzo", "Satisfaccion", dataset, PlotOrientation.VERTICAL, false, true, false);
		ChartFrame frame = new ChartFrame("Ingenieria de Sistemas Basados en el Conocimiento", chart);
		frame.pack();
		frame.setVisible(true);
	}
}


